<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>事件代理</title>
    <style>
      a {
        text-decoration: none;
      }
    </style>
  </head>

  <body>
    <button id="btn1">一个按钮</button>
    <div id="div3">
      <a href="#">a1</a> <br />
      <a href="#">a2</a> <br />
      <a href="#">a3</a> <br />
      <a href="#">a4</a> <br />
      <button>加载更多</button>
    </div>
  </body>

  <script>
    // 事件代理（delegate）也称为事件托管或事件委托，就是把目标节点的事件绑定到祖先节点上。这种简单而优雅的事件注册方式是基于事件传播过程中，逐层冒泡总能被祖先节点捕获。
    // 这样做的好处：优化代码，提升运行性能，真正把 HTML 和 JavaScript 分离，也能防止出现在动态添加或删除节点过程中注册的事件丢失的现象

    // 普通绑定
    const btn1 = document.getElementById("btn1");

    // 事件代理
    // 1. 代码简洁
    // 2. 减少浏览器内存的占用
    // 3. 但是不能滥用(判断代码的检验程度，不要为了用代理而用代理 要用在合适的场景下去用)

    // 通用的事件绑定函数(这样写太无聊啦 如果在面试的过程中写这样的代码 就没有面试的必要啦)
    // function bindEvent(elem, type, fn) {
    //     elem.addEventListener(type, fn)
    // }

    // 我们现在变一下 就让他变得 让他支持普通的按钮的click,也能支持到 能在代理的情况下监听

    // selector 相当于一个标签选择器
    function bindEvent(elem, type, selector, fn) {
      // 判断 seletor 的类型是否是一个函数 如果是一个函数那么 把 selector 的值赋值给 fn ，再把 selector 的值置为 null
      if (typeof selector == "function") {
        fn = selector;
        selector = null;
      }
      elem.addEventListener(type, (event) => {
        const target = event.target; // 触发的元素
        if (selector) {
          // 代理
          // target.matches(selector) 主要是用来判断当前DOW节点是否能完全匹配对应的CSS选择器，如果匹配成功，返回true，反之则返回false
          if (target.matches(selector)) {
            fn.call(target, event);
          }
        } else {
          // 普通绑定
          fn.call(target, event);
        }
      });
    }

    // 代理绑定
    const div3 = document.getElementById("div3");

    bindEvent(div3, "click", "a", function (event) {
      event.preventDefault(); // 阻止默认事件
      // const target = event.target // 获取触发的元素
      // // 不要在代码里面判断这些乱七八糟的东西
      // if (target.nodeName === "A") {
      //     alert(target.innerHTML)
      // }
      // this 永远都是触发事件元素
      alert(this.innerHTML);
    });

    bindEvent(btn1, "click", function (event) {
      event.preventDefault(); // 阻止默认事件
      // const target = event.target // 获取触发的元素
      alert(this.innerHTML);
    });
  </script>
</html>
